/**
 * SceneGame_Level
 * 	@brief  Level generator
 * 	@author Bruno Miguel de Oliveira Tamer <bmotamer@gmail.com>
 */

using UnityEngine;

public class SceneGame_Level : MonoBehaviour
{
	
	public  SceneGame_Camera Camera;
	public  SceneGame_Player Player;
	public  SceneGame_Bullet Bullet;
	public  GameObject       StraightPrefab;
	public  GameObject       CurvePrefab;
	public  GameObject       VirusPrefab;
	public  GameObject       ArrowPrefab;
	public  int              PreLoadedChunks;
	public  Vector2          Bounds;
	private GameObject[]     _Path;
	private GameObject[]     _Enemies;
	
	public void Start ()
	{
		PreLoadedChunks = Mathf.Clamp(PreLoadedChunks, 8, int.MaxValue);
		if ((PreLoadedChunks % 2) == 0)
			++PreLoadedChunks;
		_Path    = new GameObject[PreLoadedChunks];
		_Enemies = new GameObject[PreLoadedChunks];
		for (int i = 0; i < _Path.Length; i++)
			_Path[i] = i < 4 ? (GameObject)Instantiate(StraightPrefab, new Vector3(0.0f, 0.0f, i * 414.0f), Quaternion.identity) : MakePath(i);
	}
	
	public void Update()
	{
		int   i        = Mathf.FloorToInt(0.5f * _Path.Length);
		float distance = Camera.transform.position.z - _Path[i].transform.position.z;
		if (distance >= 0.0f)
		{
			Player.Displacement = (Player.Displacement - _Path[i].transform.position.z);
			float zOffset = Player.Offset.y + Player.Displacement;
			Bullet.transform.position = new Vector3(
				Bullet.transform.position.x,
				Bullet.transform.position.y,
				zOffset + (Bullet.transform.position.z - Player.transform.position.z)
			);
			Player.transform.position = new Vector3(Player.transform.position.x, 0.0f, zOffset);
			Camera.Update();
			
			int j, k;
			GameObject enemy, path;
			for (j = 0; j < i; j++)
			{
				Destroy(_Path[j]);
				enemy = _Enemies[j];
				if (enemy)
					Destroy(enemy);
			}
			for (j = i; j < _Path.Length; j++)
			{
				path     = _Path[j];
				enemy    = _Enemies[j];
				k        = j - i;
				_Path[k] = path;
				_Path[k].transform.position = new Vector3(path.transform.position.x, 0.0f, k * 414.0f);
				if (enemy)
				{
					_Enemies[k] = enemy;
					_Enemies[k].transform.position = new Vector3(enemy.transform.position.x, 0.0f, path.transform.position.z);
				}
			}
			for (j = _Path.Length - i; j < _Path.Length; j++)
				_Path[j] = MakePath(j);
		}
	}
	
	public GameObject MakePath(int i)
	{
		GameObject obj      = null;
		GameObject enemyObj = null;
		Vector3    pos      = Vector3.zero;
		Vector3    enemyPos = Vector3.zero;
		if (_Path[i - 1].name == StraightPrefab.name + "(Clone)")
		{
			obj = Random.Range(0, 100) <= 25 ? StraightPrefab : CurvePrefab;
			pos = _Path[i - 1].transform.position + new Vector3(0.0f, 0.0f, 414.0f);
		}
		else if (_Path[i - 1].name == CurvePrefab.name + "(Clone)")
		{
			obj = Random.Range(0, 100) <= 25 ? CurvePrefab : StraightPrefab;
			pos = _Path[i - 1].transform.position + new Vector3(_Path[i - 1].transform.rotation.eulerAngles.z == 0.0f ? -307.5f : 307.5f, 0.0f, 414.0f);
		}
		
		if (Random.Range(0, 100) >= 15)
		{
			if (obj == CurvePrefab)
			{
				enemyObj = VirusPrefab;
				enemyPos = pos;
			}
			else if (Random.Range(0, 100) <= 50)
			{
				enemyObj = VirusPrefab;
				enemyPos = pos;
			}
			else
			{
				enemyObj = ArrowPrefab;
				enemyPos = pos - new Vector3(132.0f, 0.0f, 0.0f);
			}
		}
		obj = (GameObject)Instantiate(obj, pos, Quaternion.identity);
		if ( (obj.name == CurvePrefab.name + "(Clone)") && ((pos.x <= Bounds.x) || ((pos.x < Bounds.y) && (Random.Range(0, 100) <= 50))) )
		{
			obj.transform.rotation = Quaternion.Euler(
				new Vector3(
					obj.transform.rotation.eulerAngles.x,
					obj.transform.rotation.eulerAngles.y,
					180.0f
				)
			);
			obj.transform.localScale = new Vector3(
				obj.transform.localScale.x,
				-obj.transform.localScale.y,
				obj.transform.localScale.z
			);
		}
		_Enemies[i] = enemyObj ? (GameObject)Instantiate(
			enemyObj,
			enemyPos + new Vector3(obj.transform.localScale.y < 0 ? 153.75f : 0.0f, 0.0f, 0.0f),
			Quaternion.Euler(0.0f, enemyObj.name == "ArrowPrefab" ? 90.0f : 0.0f, 0.0f)
		) : null;
		return obj;
	}
	
}